//
// GPSMapEdit
// (c) Konstantin Galichsky (kg@geopainting.com), 2002-2007
//
// Changing of postal address items.
//

# include "StdAfx.h"
# include "ChangePAI.h"
# include "UndoRedo.h"
# include "Label.h"

class CDeletePAIAction : public CEditAction {
  public:
	CDeletePAIAction (pa_item_t * _pPAI) : m_pPAI (_pPAI) {}

	virtual void GetName (string_t & _str) const;
	virtual cu_t CanUndo () const {return cuYes;}
	virtual bool Do ();
	virtual void Undo ();
	virtual void Redo ();

  private:
	pa_item_t * m_pPAI;
};

void CDeletePAIAction::GetName (string_t & _str) const {
	CCritSec::CLock lock (g_cs);

	_str.append ("delete [");
	_str.append (m_pPAI->strName);
	_str.append ("]");
}

bool CDeletePAIAction::Do () {
	CCritSec::CLock lock (g_cs);

	assert (m_pPAI);
	m_pPAI->bDeleted = true;

	return true;
}

void CDeletePAIAction::Undo () {
	CCritSec::CLock lock (g_cs);

	assert (m_pPAI);
	m_pPAI->bDeleted = false;
}

void CDeletePAIAction::Redo () {
	CDeletePAIAction::Do ();
}

//////////////////////////////////////////

class CRenamePAIAction : public CEditAction {
  public:
	CRenamePAIAction (pa_item_t * _pPAI, const string_t & _strName) :
		m_pPAI (_pPAI),
		m_strNameNew (_strName),
		m_strNameOld (_pPAI->strName),
		m_bAbbrev (false)
	{}

	CRenamePAIAction (pa_item_t * _pPAI, const string_t & _strName, const string_t & _strAbbrevName) :
		m_pPAI (_pPAI),
		m_strNameNew (_strName),
		m_strNameOld (_pPAI->strName),
		m_strAbbrevNameNew (_strAbbrevName),
		m_strAbbrevNameOld (static_cast<pa_item_a_t *> (_pPAI)->strAbbrevName),
		m_bAbbrev (true)
	{}

	virtual void GetName (string_t & _str) const;
	virtual cu_t CanUndo () const {return cuYes;}
	virtual bool Do ();
	virtual void Undo ();
	virtual void Redo ();

  private:
	pa_item_t * const m_pPAI;

	string_t m_strNameNew;
	string_t m_strNameOld;

	bool m_bAbbrev;
	string_t m_strAbbrevNameNew;
	string_t m_strAbbrevNameOld;
};

void CRenamePAIAction::GetName (string_t & _str) const {
	CCritSec::CLock lock (g_cs);

	_str.append ("rename [");
	_str.append (m_strNameOld);
	_str.append ("]");
}

bool CRenamePAIAction::Do () {
	CCritSec::CLock lock (g_cs);

	assert (m_pPAI);
	m_pPAI->strName = m_strNameNew;
	if (m_bAbbrev)
		static_cast<pa_item_a_t *> (m_pPAI)->strAbbrevName = m_strAbbrevNameNew;

	return true;
}

void CRenamePAIAction::Undo () {
	CCritSec::CLock lock (g_cs);

	assert (m_pPAI);
	m_pPAI->strName = m_strNameOld;
	if (m_bAbbrev)
		static_cast<pa_item_a_t *> (m_pPAI)->strAbbrevName = m_strAbbrevNameOld;
}

void CRenamePAIAction::Redo () {
	CRenamePAIAction::Do ();
}

//////////////////////////////////////////

class CAddCountryAction : public CEditAction {
  public:
	CAddCountryAction (const string_t & _strName, const string_t & _strAbbrevName) :
		m_strName (_strName),
		m_strAbbrevName (_strAbbrevName),
		m_pCountry (NULL)
	{}

	virtual void GetName (string_t & _str) const;
	virtual cu_t CanUndo () const {return cuYes;}
	virtual bool Do ();
	virtual void Undo ();
	virtual void Redo ();

  private:
	string_t m_strName;
	string_t m_strAbbrevName;
	country_t * m_pCountry;
};

void CAddCountryAction::GetName (string_t & _str) const {
	CCritSec::CLock lock (g_cs);

	_str.append ("add [");
	_str.append (m_strName);
	_str.append ("]");
}

bool CAddCountryAction::Do () {
	CCritSec::CLock lock (g_cs);

	g_map.Countries.push_back (country_t ());
	country_t & country = g_map.Countries.back ();

	country.strName       = m_strName;
	country.strAbbrevName = m_strAbbrevName;

	assert (m_pCountry == NULL);
	m_pCountry = & country;

	return true;
}

void CAddCountryAction::Undo () {
	CCritSec::CLock lock (g_cs);

	assert (m_pCountry);
	m_pCountry->bDeleted = true;
}

void CAddCountryAction::Redo () {
	CCritSec::CLock lock (g_cs);

	assert (m_pCountry);
	m_pCountry->bDeleted = false;
}

//////////////////////////////////////////

class CAddRegionAction : public CEditAction {
  public:
	CAddRegionAction (const string_t & _strName, country_t * _pCountry) :
		m_strName (_strName),
		m_pCountry (_pCountry),
		m_pRegion (NULL)
	{}

	virtual void GetName (string_t & _str) const;
	virtual cu_t CanUndo () const {return cuYes;}
	virtual bool Do ();
	virtual void Undo ();
	virtual void Redo ();

  private:
	string_t    const m_strName;
	country_t * const m_pCountry;

	region_t * m_pRegion;
};

void CAddRegionAction::GetName (string_t & _str) const {
	CCritSec::CLock lock (g_cs);

	_str.append ("add [");
	_str.append (m_strName);
	_str.append ("]");
}

bool CAddRegionAction::Do () {
	CCritSec::CLock lock (g_cs);

	g_map.Regions.push_back (region_t ());
	region_t & region = g_map.Regions.back ();

	region.strName = m_strName;
	region.pCountry = m_pCountry;

	assert (m_pRegion == NULL);
	m_pRegion = & region;

	return true;
}

void CAddRegionAction::Undo () {
	CCritSec::CLock lock (g_cs);

	assert (m_pRegion);
	m_pRegion->bDeleted = true;
}

void CAddRegionAction::Redo () {
	CCritSec::CLock lock (g_cs);

	assert (m_pRegion);
	m_pRegion->bDeleted = false;
}

//////////////////////////////////////////

class CAddCityAction : public CEditAction {
  public:
	CAddCityAction (const string_t & _strName, region_t * _pRegion) :
		m_strName (_strName),
		m_pRegion (_pRegion),
		m_pCity (NULL)
	{}

	virtual void GetName (string_t & _str) const;
	virtual cu_t CanUndo () const {return cuYes;}
	virtual bool Do ();
	virtual void Undo ();
	virtual void Redo ();

  private:
	string_t   const m_strName;
	region_t * const m_pRegion;

	city_t * m_pCity;
};

void CAddCityAction::GetName (string_t & _str) const {
	CCritSec::CLock lock (g_cs);

	_str.append ("add [");
	_str.append (m_strName);
	_str.append ("]");
}

bool CAddCityAction::Do () {
	CCritSec::CLock lock (g_cs);

	g_map.Cities.push_back (city_t ());
	city_t & city = g_map.Cities.back ();

	city.strName = m_strName;
	city.pRegion = m_pRegion;

	assert (m_pCity == NULL);
	m_pCity = & city;

	return true;
}

void CAddCityAction::Undo () {
	CCritSec::CLock lock (g_cs);

	assert (m_pCity);
	m_pCity->bDeleted = true;
}

void CAddCityAction::Redo () {
	CCritSec::CLock lock (g_cs);

	assert (m_pCity);
	m_pCity->bDeleted = false;
}

//////////////////////////////////////////

class CAddZipAction : public CEditAction {
  public:
	CAddZipAction (const string_t & _strCode) :
		m_strCode (_strCode),
		m_pZip (NULL)
	{}

	virtual void GetName (string_t & _str) const;
	virtual cu_t CanUndo () const {return cuYes;}
	virtual bool Do ();
	virtual void Undo ();
	virtual void Redo ();

  private:
	string_t m_strCode;
	zip_t  * m_pZip;
};

void CAddZipAction::GetName (string_t & _str) const {
	CCritSec::CLock lock (g_cs);

	_str.append ("add [");
	_str.append (m_strCode);
	_str.append ("]");
}

bool CAddZipAction::Do () {
	CCritSec::CLock lock (g_cs);

	g_map.Zips.push_back (zip_t ());
	zip_t & zip = g_map.Zips.back ();

	zip.strName = m_strCode;

	assert (m_pZip == NULL);
	m_pZip = & zip;

	return true;
}

void CAddZipAction::Undo () {
	CCritSec::CLock lock (g_cs);

	assert (m_pZip);
	m_pZip->bDeleted = true;
}

void CAddZipAction::Redo () {
	CCritSec::CLock lock (g_cs);

	assert (m_pZip);
	m_pZip->bDeleted = false;
}

//////////////////////////////////////////

class CAddHighwayAction : public CEditAction {
  public:
	CAddHighwayAction (const string_t & _strName, region_t * _pRegion) :
		m_strName (_strName),
		m_pRegion (_pRegion),
		m_pHighway (NULL)
	{}

	virtual void GetName (string_t & _str) const;
	virtual cu_t CanUndo () const {return cuYes;}
	virtual bool Do ();
	virtual void Undo ();
	virtual void Redo ();

  private:
	string_t   const m_strName;
	region_t * const m_pRegion;

	highway_t * m_pHighway;
};

void CAddHighwayAction::GetName (string_t & _str) const {
	CCritSec::CLock lock (g_cs);

	_str.append ("add [");
	_str.append (m_strName);
	_str.append ("]");
}

bool CAddHighwayAction::Do () {
	CCritSec::CLock lock (g_cs);

	g_map.Highways.push_back (highway_t ());
	highway_t & highway = g_map.Highways.back ();

	highway.strName = m_strName;
	highway.pRegion = m_pRegion;

	assert (m_pHighway == NULL);
	m_pHighway = & highway;

	return true;
}

void CAddHighwayAction::Undo () {
	CCritSec::CLock lock (g_cs);

	assert (m_pHighway);
	m_pHighway->bDeleted = true;
}

void CAddHighwayAction::Redo () {
	CCritSec::CLock lock (g_cs);

	assert (m_pHighway);
	m_pHighway->bDeleted = false;
}

//////////////////////////////////////////

void DeletePAI (pa_item_t * _pPAI) {
	PerformEditAction (new CDeletePAIAction (_pPAI));
}

void RenamePAI (pa_item_t * _pPAI, const string_t & _strName) {
	PerformEditAction (new CRenamePAIAction (_pPAI, _strName));
}

void RenamePAI (pa_item_t * _pPAI, const string_t & _strName, const string_t & _strAbbrevName) {
	PerformEditAction (new CRenamePAIAction (_pPAI, _strName, _strAbbrevName));
}

void AddCountry (const string_t & _strName, const string_t & _strAbbrevName) {
	PerformEditAction (new CAddCountryAction (_strName, _strAbbrevName));
}

void AddRegion (const string_t & _strName, country_t * _pCountry) {
	PerformEditAction (new CAddRegionAction (_strName, _pCountry));
}

void AddCity (const string_t & _strName, region_t * _pRegion) {
	PerformEditAction (new CAddCityAction (_strName, _pRegion));
}

void AddZip (const string_t & _strCode) {
	PerformEditAction (new CAddZipAction (_strCode));
}

void AddHighway (const string_t & _strName, region_t * _pRegion) {
	PerformEditAction (new CAddHighwayAction (_strName, _pRegion));
}

////////////////////////////////////////////////////////

class CSetRegionAction : public CEditAction {
  public:
	CSetRegionAction (city_t * _pCity, region_t * _pRegion) :
		m_pCity (_pCity),
		m_pRegionNew (_pRegion),
		m_pRegionOld (_pCity->pRegion)
	{}

	virtual void GetName (string_t & _str) const;
	virtual cu_t CanUndo () const {return cuYes;}
	virtual bool Do ();
	virtual void Undo ();
	virtual void Redo ();

  private:
	city_t * const m_pCity;

	region_t * const m_pRegionNew;
	region_t * const m_pRegionOld;
};

void CSetRegionAction::GetName (string_t & _str) const {
	CCritSec::CLock lock (g_cs);

	_str.append ("change [");
	_str.append (m_pCity->strName);
	_str.append ("]");
}

bool CSetRegionAction::Do () {
	CCritSec::CLock lock (g_cs);

	assert (m_pCity);
	m_pCity->pRegion = m_pRegionNew;

	return true;
}

void CSetRegionAction::Undo () {
	CCritSec::CLock lock (g_cs);

	assert (m_pCity);
	m_pCity->pRegion = m_pRegionOld;
}

void CSetRegionAction::Redo () {
	CSetRegionAction::Do ();
}

void SetRegion (city_t * _pCity, region_t * _pRegion) {
	PerformEditAction (new CSetRegionAction (_pCity, _pRegion));
}